home *** CD-ROM | disk | FTP | other *** search
/ CD/PC Actual 31 / PC Actual CD 31.iso / dists / SRC / SLIBEXEC.AA / SLIBEXEC / libexec / ftpd / popen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-05-17  |  5.7 KB  |  210 lines

  1. /*
  2.  * Copyright (c) 1988, 1993, 1994
  3.  *    The Regents of the University of California.  All rights reserved.
  4.  *
  5.  * This code is derived from software written by Ken Arnold and
  6.  * published in UNIX Review, Vol. 6, No. 8.
  7.  *
  8.  * Redistribution and use in source and binary forms, with or without
  9.  * modification, are permitted provided that the following conditions
  10.  * are met:
  11.  * 1. Redistributions of source code must retain the above copyright
  12.  *    notice, this list of conditions and the following disclaimer.
  13.  * 2. Redistributions in binary form must reproduce the above copyright
  14.  *    notice, this list of conditions and the following disclaimer in the
  15.  *    documentation and/or other materials provided with the distribution.
  16.  * 3. All advertising materials mentioning features or use of this software
  17.  *    must display the following acknowledgement:
  18.  *    This product includes software developed by the University of
  19.  *    California, Berkeley and its contributors.
  20.  * 4. Neither the name of the University nor the names of its contributors
  21.  *    may be used to endorse or promote products derived from this software
  22.  *    without specific prior written permission.
  23.  *
  24.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  25.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  26.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  27.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  28.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  29.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  30.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  31.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  32.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  33.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  34.  * SUCH DAMAGE.
  35.  */
  36.  
  37. #ifndef lint
  38. #if 0
  39. static char sccsid[] = "@(#)popen.c    8.3 (Berkeley) 4/6/94";
  40. #endif
  41. static const char rcsid[] =
  42.     "$Id: popen.c,v 1.15 1998/05/18 00:06:28 ache Exp $";
  43. #endif /* not lint */
  44.  
  45. #include <sys/types.h>
  46. #include <sys/wait.h>
  47.  
  48. #include <errno.h>
  49. #include <glob.h>
  50. #include <signal.h>
  51. #include <stdio.h>
  52. #include <stdlib.h>
  53. #include <string.h>
  54. #include <unistd.h>
  55.  
  56. #include "extern.h"
  57. #ifdef    INTERNAL_LS
  58. #include "pathnames.h"
  59. #include <syslog.h>
  60. #include <time.h>
  61. #include <varargs.h>
  62. #endif
  63.  
  64. #define    MAXUSRARGS    100
  65. #define    MAXGLOBARGS    1000
  66.  
  67. /*
  68.  * Special version of popen which avoids call to shell.  This ensures noone
  69.  * may create a pipe to a hidden program as a side effect of a list or dir
  70.  * command.
  71.  */
  72. static int *pids;
  73. static int fds;
  74.  
  75. FILE *
  76. ftpd_popen(program, type)
  77.     char *program, *type;
  78. {
  79.     char *cp;
  80.     FILE *iop;
  81.     int argc, gargc, pdes[2], pid;
  82.     char **pop, *argv[MAXUSRARGS], *gargv[MAXGLOBARGS];
  83.  
  84.     if (((*type != 'r') && (*type != 'w')) || type[1])
  85.         return (NULL);
  86.  
  87.     if (!pids) {
  88.         if ((fds = getdtablesize()) <= 0)
  89.             return (NULL);
  90.         if ((pids = (int *)malloc((u_int)(fds * sizeof(int)))) == NULL)
  91.             return (NULL);
  92.         memset(pids, 0, fds * sizeof(int));
  93.     }
  94.     if (pipe(pdes) < 0)
  95.         return (NULL);
  96.  
  97.     /* break up string into pieces */
  98.     for (argc = 0, cp = program; argc < MAXUSRARGS; cp = NULL) {
  99.         if (!(argv[argc++] = strtok(cp, " \t\n")))
  100.             break;
  101.     }
  102.     argv[argc - 1] = NULL;
  103.  
  104.     /* glob each piece */
  105.     gargv[0] = argv[0];
  106.     for (gargc = argc = 1; argv[argc] && gargc < (MAXGLOBARGS-1); argc++) {
  107.         glob_t gl;
  108.         int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
  109.  
  110.         memset(&gl, 0, sizeof(gl));
  111.         if (glob(argv[argc], flags, NULL, &gl))
  112.             gargv[gargc++] = strdup(argv[argc]);
  113.         else
  114.             for (pop = gl.gl_pathv; *pop && gargc < (MAXGLOBARGS-1);
  115.                  pop++)
  116.                 gargv[gargc++] = strdup(*pop);
  117.         globfree(&gl);
  118.     }
  119.     gargv[gargc] = NULL;
  120.  
  121.     iop = NULL;
  122. #ifdef    INTERNAL_LS
  123.     fflush(NULL);
  124.     pid = (strcmp(gargv[0], _PATH_LS) == 0) ? fork() : vfork();
  125. #else
  126.     pid = vfork();
  127. #endif
  128.     switch(pid) {
  129.     case -1:            /* error */
  130.         (void)close(pdes[0]);
  131.         (void)close(pdes[1]);
  132.         goto pfree;
  133.         /* NOTREACHED */
  134.     case 0:                /* child */
  135.         if (*type == 'r') {
  136.             if (pdes[1] != STDOUT_FILENO) {
  137.                 dup2(pdes[1], STDOUT_FILENO);
  138.                 (void)close(pdes[1]);
  139.             }
  140.             dup2(STDOUT_FILENO, STDERR_FILENO); /* stderr too! */
  141.             (void)close(pdes[0]);
  142.         } else {
  143.             if (pdes[0] != STDIN_FILENO) {
  144.                 dup2(pdes[0], STDIN_FILENO);
  145.                 (void)close(pdes[0]);
  146.             }
  147.             (void)close(pdes[1]);
  148.         }
  149. #ifdef    INTERNAL_LS
  150.         if (strcmp(gargv[0], _PATH_LS) == 0) {
  151.             extern    int optreset;
  152.             /* Reset getopt for ls_main() */
  153.             optreset = optind = optopt = 1;
  154.             /* Close syslogging to remove pwd.db missing msgs */
  155.             closelog();
  156.             /* Trigger to sense new /etc/localtime after chroot */
  157.             if (getenv("TZ") == NULL) {
  158.                 setenv("TZ", "", 0);
  159.                 tzset();
  160.                 unsetenv("TZ");
  161.                 tzset();
  162.             }
  163.             exit(ls_main(gargc, gargv));
  164.         }
  165. #endif
  166.         execv(gargv[0], gargv);
  167.         _exit(1);
  168.     }
  169.     /* parent; assume fdopen can't fail...  */
  170.     if (*type == 'r') {
  171.         iop = fdopen(pdes[0], type);
  172.         (void)close(pdes[1]);
  173.     } else {
  174.         iop = fdopen(pdes[1], type);
  175.         (void)close(pdes[0]);
  176.     }
  177.     pids[fileno(iop)] = pid;
  178.  
  179. pfree:    for (argc = 1; gargv[argc] != NULL; argc++)
  180.         free(gargv[argc]);
  181.  
  182.     return (iop);
  183. }
  184.  
  185. int
  186. ftpd_pclose(iop)
  187.     FILE *iop;
  188. {
  189.     int fdes, omask, status;
  190.     pid_t pid;
  191.  
  192.     /*
  193.      * pclose returns -1 if stream is not associated with a
  194.      * `popened' command, or, if already `pclosed'.
  195.      */
  196.     if (pids == 0 || pids[fdes = fileno(iop)] == 0)
  197.         return (-1);
  198.     (void)fclose(iop);
  199.     omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
  200.     while ((pid = waitpid(pids[fdes], &status, 0)) < 0 && errno == EINTR)
  201.         continue;
  202.     (void)sigsetmask(omask);
  203.     pids[fdes] = 0;
  204.     if (pid < 0)
  205.         return (pid);
  206.     if (WIFEXITED(status))
  207.         return (WEXITSTATUS(status));
  208.     return (1);
  209. }
  210.